<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>Limb3 JS Tests</title>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <script src="../lib/prototype.js" type="text/javascript"></script>
  <script src="../lib/unittest.js" type="text/javascript"></script>

  <script src="../../shared/limb.js" type="text/javascript"></script>
  <script src="../../shared/limb/Browser.js" type="text/javascript"></script>
  <link rel="stylesheet" href="../test.css" type="text/css" />
</head>
<body>
<h1>Limb.Object test</h1>

<!-- Log output -->
<div id="testlog"> </div>

<!-- Tests follow -->
<script type="text/javascript" language="javascript" charset="utf-8">
// <![CDATA[

new Test.Unit.Runner({
  tearDown: function()
  {
    if(MyInterface)
    {
      delete MyInterface;
      MyInterface = null;
    }

    if(MySuperClass)
    {
      delete MySuperClass;
      MySuperClass = null;
    }

    delete MyClass;
    MyClass = null;
  },

  testConsturctCall: function()
  {
    Limb.Class('MyClass',
    {
      __construct: function() { this.construct_called = true; }
    });

    var test_object = new MyClass();
    this.assert(test_object.construct_called, '__construct not called during construction');
  },

  testConsturctCallWithArguments: function()
  {
    Limb.Class('MyClass',
    {
      __construct: function(arg1) { if(arg1) this.construct_called = true; }
    });

    var test_object = new MyClass(true);
    this.assert(test_object.construct_called, 'Arguments not passed to __construct');
  },

  testInheritsWithoutBody: function()
  {
    Limb.Class('MySuperClass',
    {
      returnFive: function() { return 5; }
    });

    Limb.Class('MyClass').inherits('MySuperClass');

    var test_object = new MyClass();
    this.assert(typeof(test_object.returnFive) == 'function', 'Object prototype not extended from parent class');
    this.assertEqual(test_object.returnFive(), 5, 'Object prototype not extended from parent class');
  },

  testInherits: function()
  {
    Limb.Class('MySuperClass',
    {
      returnFive: function() { return 5; }
    });

    Limb.Class('MyClass').inherits('MySuperClass',
    {
      returnSeven: function() { return 7; }
    });

    var test_object = new MyClass();
    this.assert(typeof(test_object.returnFive) == 'function', 'Object prototype not extended from parent class');
    this.assertEqual(test_object.returnFive(), 5, 'Object prototype not extended from parent class');

    this.assert(typeof(test_object.returnSeven) == 'function', 'Object prototype not extended from passed body');
    this.assertEqual(test_object.returnSeven(), 7, 'Object prototype not extended from passed body');
  },

  testSettingParentClass: function()
  {
    Limb.Class('MySuperClass',
    {
      returnFive: function() { return 5; }
    });

    Limb.Class('MyClass').inherits('MySuperClass',
    {
      returnFivePlusSeven: function() { return this.parent.returnFive() + 7; }
    });

    var test_object = new MyClass();
    this.assert(typeof(test_object.parent) == 'object', 'Parent class is not set');
    this.assertEqual(test_object.returnFivePlusSeven(), 12, 'Parent method not called');
  },

  testConstructParentWithArguments: function()
  {
    Limb.Class('MySuperClass',
    {
      __construct: function(arg1) { if(arg1) this.parent_constructor_called = true; }
    });

    Limb.Class('MyClass').inherits('MySuperClass');

    var test_object = new MyClass(true);
    this.assert(test_object.parent_constructor_called, 'Parent __construct called without arguments');
  },

  testMethodOverride: function()
  {
    Limb.Class('MySuperClass',
    {
      getClassName: function() { return 'MySuperClass'; }
    });

    Limb.Class('MyClass').inherits('MySuperClass',
    {
      getClassName: function() { return 'MyClass'; }
    });

    var test_object = new MyClass();
    this.assertEqual(test_object.getClassName(), 'MyClass', 'Child method does not override parents method');

    var test_super_object = new MySuperClass();
    this.assertEqual(test_super_object.getClassName(), 'MySuperClass', 'Child overrides method in parent class');
  },

  testImplementIterface: function()
  {
    Limb.Interface('MyInterface',
    {
      returnFive: function() {}
    });

    Limb.Class('MyClass').implements('MyInterface',
    {
      returnFive: function() { return 5; }
    });

    var test_object = new MyClass();
    this.assertEqual(5, test_object.returnFive(), 'Method not implemented');
  },

  testFailWhenIterfaceNotFullyImplemented: function()
  {
    Limb.Interface('MyInterface',
    {
      returnFive: function() {}
    });

    try
    {
      Limb.Class('MyClass').implements('MyInterface',
      {
        returnSeven: function() { return 7; }
      });

      this.assert(false, 'Implements not throws exception when interface not fully implemented');
    }
    catch(error)
    {
      this.assertEqual('InterfaceException', error.getType(), 'Exception type wrong');
      this.assertEqual('Method \'returnFive\' not implemented', error.getMessage(), 'Exception message wrong');
    }
  },

  testToString: function()
  {
    if(Limb.Browser.is_ie)
      return;

    Limb.Class('MyClass');
    var test_object = new MyClass();

    this.assertEqual('[ object MyClass ]', test_object.toString());
  }
});

// ]]>
</script>
</body>
</html>